<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <canvas id="canvas" width="1800px" height="800px"></canvas>
  </body>
  <script>
    /**
     * 通过点击画布，就绘制一个点
     * @author liaoJie
     * @since 2025-05-10 17:00:14
     */

    function randomColor() {
      const randomChannel = () => Math.floor(Math.random() * 256);
      return [randomChannel(), randomChannel(), randomChannel()];
    }

    /**
     * @param {WebGLRenderingContext} gl
     */
    function createShader(gl, type, source) {
      const shader = gl.createShader(type);
      gl.shaderSource(shader, source);
      gl.compileShader(shader);
      return shader;
    }

    const vsSource = `
      // 设置浮点数精度为中等精度
      precision mediump float;
      // 接收点在 canvas 坐标系上的坐标 (x, y)
      attribute vec2 a_Position;
      // 接收 canvas 的宽高尺寸
      attribute vec2 a_Screen_Size;

      void main() {
        // 将屏幕坐标系转化为裁剪坐标
        vec2 position = (a_Position / a_Screen_Size) * 2.0 - 1.0;
        position = position * vec2(1.0, -1.0);
        // 声明顶点位置
        gl_Position = vec4(position, 0, 1);

        // 绘制点的大小
        gl_PointSize = 100.0;
      }
    `;

    const fsSource = `
      precision mediump float;
      // 颜色
      uniform vec4 u_Color;


      void main() {
        // 设置像素填充颜色
        vec4 color = u_Color / vec4(255, 255, 255, 1);
        gl_FragColor = color;
      }
    `;

    /**
     * @type {HTMLCanvasElement}
     */
    const canvas = document.getElementById('canvas');
    /**
     * @type {WebGLRenderingContext} gl
     */
    const gl = canvas.getContext('webgl');

    // 创建顶点着色器
    const vShader = createShader(gl, gl.VERTEX_SHADER, vsSource);
    // 创建片元着色器
    const fShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);

    // 创建着色器程序
    const program = gl.createProgram();
    gl.attachShader(program, vShader);
    gl.attachShader(program, fShader);
    gl.linkProgram(program);
    gl.useProgram(program);

    const a_Position = gl.getAttribLocation(program, 'a_Position');
    const a_Screen_Size = gl.getAttribLocation(program, 'a_Screen_Size');
    const u_Color = gl.getUniformLocation(program, 'u_Color');
    gl.vertexAttrib2f(a_Screen_Size, canvas.width, canvas.height);

    const points = [];
    canvas.addEventListener('click', (e) => {
      points.push({
        x: e.pageX,
        y: e.pageY,
        color: randomColor(),
      });

      gl.clearColor(0, 0, 0, 1);
      gl.clear(gl.COLOR_BUFFER_BIT);

      points.forEach(({ x, y, color }) => {
        gl.uniform4f(u_Color, u_Color, color[0], color[1], color[2]);
        gl.vertexAttrib2f(a_Position, x, y);
        // 从0开始绘制1个点
        gl.drawArrays(gl.POINTS, 0, 1);
      });
    });

    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
  </script>
</html>
